package com.ocom.mqsimple.business.notMeal;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ocom.common.dto.GetMealTimeDto;
import com.ocom.common.entity.card.EntityNotMealRecode;
import com.ocom.common.entity.card.EntityXfMealInfo;
import com.ocom.common.entity.master.EntityFileDownloadInfo;
import com.ocom.common.request.web.ConsTimeConfigOnShowRequest;
import com.ocom.common.request.xfrecde.NotMealRecodeRequest;
import com.ocom.common.resp.Result;
import com.ocom.common.utils.RandomUtil;
import com.ocom.mqsimple.business.access.AccessProductService;
import com.ocom.mqsimple.business.notMeal.vo.NotMealVo;
import com.ocom.mqsimple.config.ConsumeDetailExportConfig;
import com.ocom.mqsimple.config.NotMealMqConfig;
import com.ocom.mqsimple.feign.AccessClientService;
import com.ocom.mqsimple.feign.MinioClientService;
import com.ocom.mqsimple.feign.PayConfigClientService;
import com.ocom.mqsimple.feign.XfRecordFeign;
import com.ocom.redis.util.RedisUtil;
import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class NotMealMqListener {
    @Value("${save.path}")
    String excelPath;

    @Autowired
    private XfRecordFeign xfRecordFeign;

    @Resource
    RedisUtil redisUtil;


    @Autowired
    AccessClientService accessClientService;

    @Autowired
    MinioClientService minioClientService;

    @Autowired
    private PayConfigClientService payConfigClientService;

    private Logger log = LoggerFactory.getLogger(NotMealMqListener.class);

    @RabbitListener(queues = NotMealMqConfig.NOT_MEAL_EXPORT_QUEUE)
    public void process(Message message, @Headers Map<String, Object> headers, Channel channel) throws Exception {
        log.info("notMeal 消费中");
        log.info("message【{}】", message);
        String notMealMessage = new String(message.getBody(), StandardCharsets.UTF_8);
        Object requestRedis = redisUtil.get(notMealMessage);
        if (requestRedis == null) {
            log.info("ConsumeDetailExport-error:redis为空异常");
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }

        NotMealRecodeRequest request = JSON.parseObject(JSON.toJSONString(requestRedis), NotMealRecodeRequest.class);

        EntityFileDownloadInfo entityFileDownloadInfo = new EntityFileDownloadInfo();
        entityFileDownloadInfo.setId(request.getDownloadId());

        long startTime = System.currentTimeMillis();
        boolean isRun = true;
        int size =  10000;
        int page = 0;
        int sheetNo = 0;
        FileOutputStream outputStream = null;
        String filePath = excelPath + RandomUtil.getRandomString(32)  + ".xlsx";
        ConsTimeConfigOnShowRequest configOnShowRequest = new ConsTimeConfigOnShowRequest();
        configOnShowRequest.setComId(request.getComId());
        Result mealNameResult = this.payConfigClientService.GetMealNameInfo(request.getComId());

        JSONObject json= JSON.parseObject(JSON.toJSONString(mealNameResult.getData()));
        List<EntityXfMealInfo> mealTimeDtoList = JSON.parseArray(JSON.toJSONString(json.get("list")),EntityXfMealInfo.class);
        Map<String,EntityXfMealInfo> mealInfoMap = new HashMap<>();
        mealTimeDtoList.forEach(mealInfo->{
            mealInfoMap.put(mealInfo.getMealNo(),mealInfo);
        });
        try {
            outputStream = new FileOutputStream(filePath);
            ExcelWriter excelWriter = EasyExcel.write(outputStream).build();
            do {
                page++;
                request.setSize(size);
                request.setPage(page);
                Result result = this.xfRecordFeign.getNotMealRecode(request);
                if(result.getCode() != 200){
                    isRun = false;
                    break;
                }

                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(result.getData()));
                List<EntityNotMealRecode> notMealRecodes = JSON.parseArray(JSON.toJSONString(jsonObject.get("records")), EntityNotMealRecode.class);
                if(ObjectUtil.isEmpty(notMealRecodes)){
                    isRun = false;
                    break;
                }
                List<NotMealVo> notMealVos = new ArrayList<>();
                notMealRecodes.forEach(notMealRecode->{

                    EntityXfMealInfo mealInfo = mealInfoMap.get(notMealRecode.getMealNo());
                    NotMealVo notMealVo = Convert.convert(NotMealVo.class,notMealRecode);
                    notMealVo.setMealDate(DateUtil.formatDate(notMealRecode.getMealDate()));
                    notMealVo.setMealName(mealInfo.getMealName());
                    notMealVos.add(notMealVo);
                });
                //写入文件流
                WriteSheet writeSheet = EasyExcel.writerSheet(sheetNo).sheetName("未就餐").head(NotMealVo.class)
                        .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build();
                excelWriter.write(notMealVos, writeSheet);
            }while (isRun);
            excelWriter.finish();
            outputStream.flush();
        }catch (IOException e){
            e.printStackTrace();
            throw new RuntimeException("exportExcel异常,具体信息为："+e.getMessage());
        }finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            System.err.println("exportExcel结束执行时间："+(System.currentTimeMillis()-startTime));
        }


        File file1= null;
        File file=new File(filePath);
        try {

            file1=new File(filePath);
            //		MultipartFile multipartFile=FileUtil.getMultipartFile(file1);
            Result result3 = minioClientService.upload(file1);
            //删除本地
            file.delete();
            if(result3.getCode()!=200){
                //更改状态 失败
                entityFileDownloadInfo.setStatus(2l);
                accessClientService.UpdateFileStatus(entityFileDownloadInfo);
            }else{
                JSONObject jsonObject =JSON.parseObject(JSON.toJSONString( result3.getData()));
                entityFileDownloadInfo.setStatus(1l);
                entityFileDownloadInfo.setUrl(jsonObject.getString("imageUrl"));
                accessClientService.UpdateFileStatus(entityFileDownloadInfo);
            }
            long endTime = System.currentTimeMillis();
//			System.out.println(endTime-startTime);

            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            log.info("NOT_MEAL_QUEUE-end:【{}】",notMealMessage);
            log.info("System.currentTimeMillis()【{}】",System.currentTimeMillis());
        } catch (Exception e) {
            log.error("NOT_MEAL_EXCEL_QUEUE 未用餐导出IO异常 【{}】",e);
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);//继续消费该消息
        }finally {
            try {
                file1.delete();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                file.delete();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }


    /**
     * 把该监听命名为B监听
     * 监听死信队列  远程服务支付接口发送消息  该队列会接受
     * [message, headers, channel]
     *
     * @return {@link }
     * @throws
     */
    @RabbitListener(queues = ConsumeDetailExportConfig.CONSUME_DETAIL_EXPORT_DIE_QUEUE)
    public void processForDie(Message message, @Headers Map<String, Object> headers, Channel channel) throws Exception {
        //死信队列放弃
        log.info("未用餐-死信队列放弃 ， 【{}】", message);
        String notMessage = new String(message.getBody(), StandardCharsets.UTF_8);
        Object requestRedis = redisUtil.get(notMessage);
        redisUtil.dels(notMessage);

        if (requestRedis == null) {
            log.info("notMealExport-processForDie:redis为空异常");
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }

        NotMealRecodeRequest request = JSON.parseObject(JSON.toJSONString(requestRedis), NotMealRecodeRequest.class);

        EntityFileDownloadInfo entityFileDownloadInfo = new EntityFileDownloadInfo();
        entityFileDownloadInfo.setId(request.getDownloadId());

        //获取异常-跳过  失败处理

        //下载失败
        entityFileDownloadInfo.setStatus(2l);
        entityFileDownloadInfo.setRemark("死信队列-导出失败");
        accessClientService.UpdateFileStatus(entityFileDownloadInfo);

        channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
    }

}
